package com.dy.user.service.impl;

import com.dy.basic.jwt.JwtUtils;
import com.dy.basic.jwt.RsaUtils;
import com.dy.basic.jwt.UserInfo;
import com.dy.basic.service.impl.BaseServiceImpl;
import com.dy.basic.util.AjaxResult;
import com.dy.basic.util.BusinessException;
import com.dy.basic.util.MD5Utils;
import com.dy.basic.util.StrUtils;
import com.dy.system.domain.Menu;
import com.dy.system.mapper.MenuMapper;
import com.dy.system.mapper.PermissionMapper;
import com.dy.user.domain.Logininfo;
import com.dy.user.dto.AccountLoginDto;
import com.dy.user.mapper.LogininfoMapper;
import com.dy.user.service.ILogininfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.security.PrivateKey;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author dayong
 * @since 2023-03-04
 */
@Service
public class LogininfoServiceImpl extends BaseServiceImpl<Logininfo> implements ILogininfoService {

    @Autowired
    private LogininfoMapper logininfoMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Value("${jwt.rsa.pri}")
    private String jwtRsaPrivate;

    /**
     * 用户登录
     * @param dto
     * @return
     */
    @Override
    public AjaxResult accountLogin(AccountLoginDto dto) {
        // 校验参数
        // 查询该用户在数据库中有没有数据
        Logininfo logininfo = logininfoMapper.findByAccount(dto);
        if (null == logininfo){
            throw new BusinessException("账户或者密码错误");
        }
        // 比对密码是否正确
        String salt = logininfo.getSalt();
        String passwordMd5 = MD5Utils.encrypByMd5(salt + dto.getPassword());
        if (!passwordMd5.equals(logininfo.getPassword())){
            throw new BusinessException("账户或者密码错误");
        }
       // return getMap(logininfo);
        HashMap<String, Object> stringObjectHashMap = loginSuccessJwtHandler(logininfo);
        return AjaxResult.me().success(stringObjectHashMap);
    }

    private AjaxResult getMap(Logininfo logininfo) {
        // 生成token,用户的信息存入Redis中
        String token = StrUtils.getComplexRandomString(10);
        redisTemplate.opsForValue().set(token, logininfo,30, TimeUnit.MINUTES);

        // 保存到resultObj返回给前端
        HashMap<String, Object>  logininfoHashMap = new HashMap<>();
        logininfoHashMap.put("token",token);
        logininfoHashMap.put("logininfo", logininfo);
        return AjaxResult.me().success(logininfoHashMap);
    }

    /**
     * @Title: loginSuccessJwtHandler
     * @Description: 用户登录成功后生成JWT加密串并放入到map对象中
     * @Author: Mr.She
     * @Version: 1.0
     * @Date:  2022/6/30 13:23
     * @Parameters: [cn.itsource.user.domain.Logininfo]
     * @Return java.util.Map<java.lang.String,java.lang.Object>
     */
    public HashMap<String, Object> loginSuccessJwtHandler(Logininfo logininfo){
        // 1.创建UserInfo对象，存储logininfo对象，并用于后续赋值
        UserInfo userInfo = new UserInfo();
        userInfo.setLogininfo(logininfo);
        // 2.判断是后台用户登录才需要设置菜单信息、权限信息，类型为0那么就是后台用户登录
        if(logininfo.getType() == 0){
            // 2.1.获取用户权限信息，我们只需要sn权限编码即可
            List<String> permissions = permissionMapper.loadOwnPermissionByLogininId(logininfo.getId());
            // 2.2.获取用户菜单信息
            List<Menu> menus = menuMapper.loadOwnMenuByLogininId(logininfo.getId());
            // 2.3.将菜单信息，权限信息放入到userinfo对象中
            userInfo.setPermissions(permissions);
            userInfo.setMenus(menus);
        }
        // 3.根据密钥文件名称获取到密钥
        PrivateKey privateKey = RsaUtils.getPrivateKey(this.getClass().getClassLoader().getResource(jwtRsaPrivate).getFile());
        // 4.根据密钥、用户信息、获取JWT加密串
        String token = JwtUtils.generateTokenExpireInMinutes(userInfo, privateKey, 30);
        // 5.按照正常逻辑我们直接返回token给前端即可，但是那样前端需要解密，我们使用简化版本JWT，还是返回用户信息
        // 封装token、用户信息、权限信息、菜单信息给前端
        HashMap<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("logininfo", logininfo);
        map.put("permissions", userInfo.getPermissions());
        map.put("menus", userInfo.getMenus());
        return map;
    }
}
